from functools import reduce

import redis
from django.shortcuts import render
from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.utils import jwt_decode_handler
from user.models import User
from goods.models import Carousel, Goods, GoodImg, Category, GoodCollect
from goods.serializer import Carousel_Serializer, Goods_Serializer, Category_Serializer, GoodImg_Serializer, GoodCollect_Serializer


#轮播图
class CarouselView(APIView):
    def post(self, request): #获取数据库全部轮播图  序列化器输出 返回响应
        cars = Carousel.objects.all()
        ser = Carousel_Serializer(cars, many=True)
        return Response(ser.data)

#分类名--商品信息
class GoodsByCateName(APIView):
    def post(self, request):
    # 获取前端分类名  根据分类名查询数据库分类数据 反向查商品 序列化输出
        cate_name = request.data.get('categoryName')
        cates = Category.objects.get(cate_name=cate_name)
        goods = cates.goods_set.all()
        ser = Goods_Serializer(goods,many=True)
        return Response(ser.data)

#热门商品
class HotGoods(APIView):
    def post(self, request):
        # 获取前端分类名  根据分类名查询数据库分类数据 多 list 列表推导式
        # 反向查商品
        # 排序       序列化输出
        cate_name = request.data.get('categoryName')
        cates = [Category.objects.get(cate_name=i) for i in cate_name]
        goods = [i.goods_set.all() for i in cates]
        res = reduce(lambda x, y: x | y, goods).order_by('-count')
        ser = Goods_Serializer(res, many=True)
        return Response(ser.data)

#商品类别
class CatesView(APIView):
    def post(self, request):
        cates = Category.objects.all()
        ser = Category_Serializer(cates, many=True)
        return Response(ser.data)


#分类id--商品信息
class GoodsByCateId(APIView):
    def get(self, request):
        cate_id = request.query_params['categoryID']   # request.query_params 查询字符串传参
        try:
            cate = Category.objects.get(id=cate_id)
        except Exception as e:
            print(e)
            return Response({'msg': '没有此类别'})
        goods = cate.goods_set.all()
        ser = Goods_Serializer(goods, many=True)
        return Response(ser.data)

#分页器
class Page(PageNumberPagination):
    # 分页时前端查询的关键字
    page_size_query_param = 'pageSize'
    page_size_param = 'page'
    page_size = 7

# 全部商品 需要分页,先定义分页器
class GoodsView(ListAPIView):
    # queryset = GoodImg.objects.all()
    # serializer_class = GoodImg_Serializer
    queryset = Goods.objects.all()
    serializer_class = Goods_Serializer
    pagination_class = Page     #指定分页器


#商品详情
# 1 商品id--商品图片
class GoodPicture(APIView):
    def get(self, request):
        gid = request.query_params.get('gid')         #获取前端商品id 查询字符串传参
        if gid:   #id存在
            try:
                good = Goods.objects.get(id=gid)       #根据ID获取商品
            except Exception as e:
                return Response({'msg': '没有此商品', 'code': 400})
            imgs = good.goodimg_set.all()              #根据商品反向查询商品图片
            ser = GoodImg_Serializer(imgs, many=True)  #商品序列化输出 一个商品很多图片
            return Response(ser.data)
        else:   #id不存在
            return Response({'msg': '商品id获取错误', 'code': 400})

# 2 商品id--商品详情
class GoodDetail(APIView):
    def get(self, request):
        gid = request.query_params.get('gid')         #获取前端商品id 查询字符串传参
        if gid:   #id存在
            try:
                good = Goods.objects.get(id=gid)       #根据ID获取商品
            except Exception as e:
                return Response({'msg': '没有此商品', 'code': 400})
            ser = Goods_Serializer(good)  #商品序列化输出  一个商品一个详情
            return Response(ser.data)
        else:   #id不存在
            return Response({'msg': '商品id获取错误', 'code': 400})


# 历史记录
class AddHistory(APIView):
    def post(self, request):
        gid = request.data.get('productID')   #前端商品ID
        token = request.data.get('token')     #前端当前登录的token
        if not token:    # 没有token  当前未登录
            return Response({'msg': '未登录,请先登录', 'code':400})

        else:            # 有token  校验token
            payload = jwt_decode_handler(token)  # 解码token为payload
            print('payload>>>>>>>>>>', payload)  # 获取payload信息    payload>>>>>>>>>> {'user_id': 1, 'username': 'a11111', 'exp': 1649230681, 'email': ''}

            user_id = payload.get('user_id')  # 获取payload里的user_id 通过键取值

            redis_cli = redis.Redis()         # 连接redis  ()里可不写
            history = 'history_%s' %user_id   # 创建key值   history_user_id    redis的列表 {key:[val1,val2,val3....]}
            redis_cli.lrem(history, 0, gid)   # 若存在此商品,直接删除列表的所有gid   redis_cli.lrem(key, 0, val)  0:所有
            redis_cli.lpush(history, gid)     # 用户信息和商品ID写入redis
            redis_cli.close()

            return Response({'msg': '添加历史浏览记录成功', 'code': 200})

#添加收藏
class AddCollect(APIView):
    def post(self, request):       #获取前端传来的user用户 和 product_id商品ID
        dict_user = request.data.get('user')
        print('dict_user========>', dict_user)
        gid = request.data.get('product_id')

        if not dict_user:        #判断用户值是否获取到
            return Response({'msg': '获取用户信息错误', 'code': 400})
        if not gid:              #判断商品值是否获取到
            return Response({'msg': '商品错误', 'code': 400})

        try:                      #判断用户是否存在
            user = User.objects.get(username=dict_user['userName'])
        except Exception as e:
            return Response({'msg': '没有用户', 'code': 400})

        try:                      #判断商品是否存在
            good = Goods.objects.get(id=gid)
        except Exception as e:
            return Response({'msg': '没有此商品', 'code': 400})
        if GoodCollect.objects.filter(user=user, goods=good).count()>0:
            return Response({'msg': '此商品已经收藏过', 'code': 400})
        # 有商品和用户 写入数据库
        good = GoodCollect.objects.create(user=user, goods=good)
        ser = GoodCollect_Serializer(good)
        return Response({'msg': '添加收藏成功', 'code': 200, 'data':ser.data})

#我的收藏
class CollectInfo(APIView):
    def post(self, request):
        dict_user = request.data.get('user')        # 获取前端用户信息
        token = request.data.get('token')
        print('dict_user-------->', dict_user)

        if not all([dict_user, token]):            # 判断用户信息是否存在 即用户是否登录
            return Response({'msg': '请先登录', 'code': 400})

        try:     # 若存在, 验证用户信息user 与 token
            user = User.objects.get(username=dict_user['userName'])      # 验证用户信息user  user是用户所有注册信息
        except Exception as e:
            return Response({'msg': '没有此用户', 'code': 400})

        # 校验token
        payload = jwt_decode_handler(token)       # 1 token解码得到payload
        print('payload-------->>>', payload)    # 2 查看payload信息
        user_id = payload.get('user_id')        # 3 获取payload里的用户ID信息

        #验证用户传的user与token中的user是否一致, 不一致说明信息被盗用/篡改
        if user.id == user_id:     # 一致
            products = user.goodcollect_set.all()     # 用户->商品  一对多   user反向查询 该用户的收藏商品
            print('products-------->>>', products)  # 用户收藏表的信息   有用户ID 商品ID

            collect_goods = []               # 用户收藏的商品信息  商品
            for i in products:              # 该用户的收藏表信息  有多个收藏 遍历每个对象
                collect_goods.append({      #  列表.append() 拼接 添加信息进列表
                    'id': i.goods.id,       # i:收藏表中的对象 ,,,  goods:i对象的goods属性 对应商品表,,, id:商品表中属性
                    'sku_name': i.goods.sku_name,      #收藏表的商品表 查 商品属性  多查一 正向查询
                    'price': i.goods.price,
                    'selling_price': i.goods.selling_price,
                    'img': i.goods.img,
                    'title': i.goods.title,
                    'instruction': i.goods.instruction,
                })

            return Response({'msg': 'ok', 'code': 200, 'data': collect_goods})   # 返回收藏的商品信息
        else:
            return Response({'msg': '用户信息错误,请先登录', 'code': 400})


#删除收藏
class DelCollect(APIView):
    def delete(self, request):         # 1获取前端用户信息 和 收藏商品的ID  2判断用户存在否 3存在则删除他的收藏商品
        dict_user = request.data.get('user')  # 前端让打印出来看一下
        pid = request.data.get('product_id')
        print('dict_user-------->', dict_user)

        try:
            user = User.objects.get(username=dict_user['userName'])
        except Exception as e:
            return Response({'msg': '用户不存在', 'code': 400})

        GoodCollect.objects.filter(user_id=user.id, goods_id=pid).delete()
        return Response({'msg': '删除成功', 'code': 200})



